package com.apes.fn.controlling.vehicle.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.controlling.vehicle.repository.vehicleInfoInteface;
import com.apes.fn.server.servicePlan.repository.ServicePlanDao;
import com.apes.framework.api.SpringManager;
import com.apes.framework.util.Arith;
import org.apache.poi.ss.formula.functions.T;

import javax.swing.text.StyledEditorKit;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Creator: zouyc
 * CreateDate: 2021-03-19 9:23
 * Description:
 **/
public abstract class abstractVehicleinfo implements vehicleInfoInteface {

    /**
     * 根据车牌，门店获取接车数据
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONObject obtainCarData(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).vehicleCarInfo(json);
        return carArray.size() == 0 ? null : carArray.getJSONObject(0);
    }

    /**
     * 根据车牌，门店获取内协接车数据(查询所属门店)
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONObject obtainInnerPickDelUpCarData(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).vehicleInnerPickDelUpCarInfo(json);
        return carArray.size() == 0 ? null : carArray.getJSONObject(0);
    }

    /**
     * 根据车牌，门店获取内协接车数据(查询归还门店)
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONObject obtainInnerPickDelUpCarDataByOtherSideDept(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).vehicleInnerPickDelUpCarInfoByOtherSideDept(json);
        return carArray.size() == 0 ? null : carArray.getJSONObject(0);
    }

    /**
     * 根据车牌，门店获取有效的服务方案单、定损报价单、车险报案单
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray validDocuments(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).validDocuments(json);
        return carArray;
    }

    /**
     * 根据车牌，门店获取状态为确认/质检的服务方案单
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray planByConfirmQualityTest(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray array = SpringManager.getBean(ServicePlanDao.class).planByConfirmQualityTest(json);
        return array;
    }

    /**
     * 根据车牌，门店获取有效方案
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray validPlans(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).validPlans(json);
        return carArray;
    }

    /**
     * 根据车牌，门店获取有效方案
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray hasNotEndServicePlan(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).hasNotEndServicePlan(json);
        return carArray;
    }

    /**
     * 根据车牌，门店获取已记账方案
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray receivablesPlans(String deptId, String fnCustomerExpandId){
        JSONObject json = wrapParam(deptId,fnCustomerExpandId);
        JSONArray carArray = SpringManager.getBean(ServicePlanDao.class).receivablesPlans(json);
        return carArray;
    }

    private JSONObject wrapParam(String deptId, String fnCustomerExpandId){
        JSONObject json = new JSONObject();
        json.put("DEPTID",deptId);
        json.put("FNCUSTOMEREXPANDID",fnCustomerExpandId);
        return json;
    }

    /**
     * true:接车中
     * @param param
     * @return
     */
    protected boolean carState(JSONObject param){
        if(param != null) return true;
        return false;
    }


    /**
     * 根据车牌，门店获取方案数据
     * @param deptId
     * @param fnCustomerExpandId
     * @return
     */
    protected JSONArray obtainPlanData(String deptId,String fnCustomerExpandId){
        JSONObject json = new JSONObject();
        json.put("DEPTID",deptId);
        json.put("FNCUSTOMEREXPANDID",fnCustomerExpandId);
        JSONArray planArray = SpringManager.getBean(ServicePlanDao.class).vehiclePlanInfo(json);
        return planArray;
    }



    /**
     *返回是否有各个阶段的单据(待做方案，待施工，带总检，待收款)
     * @param array
     * @return
     */
    protected JSONObject planState(JSONArray array){
        JSONObject reJson = new JSONObject();
        boolean haveWaitDoPlan = false,haveWaitWork = false,haveWaitTest = false,haveWaitMoney = false; //默认四个状态中的都没有
        boolean haveWaitWorkUnLock = false,haveWaitTestUnlock = false; //其中两种状态是否存在有已解锁的单据

        boolean haveQTest = false;

        if(array.size() != 0){
            List haveWaitDoPlanList = array.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return itemJson.getDate("CONFIRM_DATE") == null;
            }).collect(Collectors.toList());

            List haveWaitWorkList = array.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return "confirm".equals(itemJson.getString("STATE")) && itemJson.getDate("CONFIRM_DATE") != null
                        && itemJson.getDate("FINISH_DATE_ITEM") == null;
            }).collect(Collectors.toList());

            List haveWaitTestList = array.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return "confirm".equals(itemJson.getString("STATE"))
                        && itemJson.getDate("FINISH_DATE_ITEM") != null;
            }).collect(Collectors.toList());
            List haveWaitMoneyList = array.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return "qualityTest".equals(itemJson.getString("STATE"));
            }).collect(Collectors.toList());

            List haveWaitWorkUnLockList = (List) haveWaitWorkList.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return itemJson.get("LOCK_STATE") == null  || !itemJson.getBoolean("LOCK_STATE");
            }).collect(Collectors.toList());

            List haveWaitTestUnLockList = (List) haveWaitTestList.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return itemJson.get("LOCK_STATE") == null  || !itemJson.getBoolean("LOCK_STATE");
            }).collect(Collectors.toList());

            List haveQTList = (List) array.stream().filter(item ->{
                JSONObject itemJson = (JSONObject)item;
                return itemJson.get("QUALITY_TEST_DATE") != null  ;
            }).collect(Collectors.toList());

            if(haveWaitDoPlanList.size() != 0) haveWaitDoPlan = true;
            if(haveWaitWorkList.size() != 0) haveWaitWork = true;
            if(haveWaitTestList.size() != 0) haveWaitTest = true;
            if(haveWaitMoneyList.size() != 0) haveWaitMoney = true;

            if(haveWaitWorkUnLockList.size() != 0) haveWaitWorkUnLock = true;
            if(haveWaitTestUnLockList.size() != 0) haveWaitTestUnlock = true;

            if(haveQTList.size() != 0) haveQTest = true;
        }
        reJson.put("haveWaitDoPlan",haveWaitDoPlan); //存在有确认前单据 AAA
        reJson.put("haveWaitWork",haveWaitWork); //存在有确认了，没有完工的单据 BBB
        reJson.put("haveWaitTest",haveWaitTest); //存在有施工完成，没有质检单据 CCC
        reJson.put("haveWaitMoney",haveWaitMoney); //存在有质检了没有收款单据 DDD

        //存在有工单解锁了的 BBB 和 CCCC
        reJson.put("haveWaitWorkUnLock",haveWaitWorkUnLock);
        reJson.put("haveWaitTestUnlock",haveWaitTestUnlock);

        reJson.put("haveConfirmPlan", haveWaitWork || haveWaitTest || haveWaitMoney);
        reJson.put("haveConfirmToReci", haveWaitWork || haveWaitTest || haveWaitMoney);

        reJson.put("haveQTest",haveQTest); //判断当前流程是否到过质检
        return reJson;
    }

    /**
     * 根据方案数据，返回各阶段
     * haveWaitWork  是否有施工单据
     * haveWaitTest 是否有质检单据
     * haveWaitMoney 是否有收款单据
     * haveLock 是否有锁定单据
     * @param array
     * @return
     */
    protected JSONObject planStateForNew(JSONArray array){
        array = Optional.ofNullable(array).orElseGet(()->new JSONArray());
        JSONObject reJson = new JSONObject();
        //检测存有无终止方案
        reJson.put("haveEndServicePlan",array.stream().filter(item->haveEndServicePlan(item)).collect(Collectors.toList()).size() == 0 ? false : true);
        //检测是否在待施工(在确定后，转工单前)
        reJson.put("isWaitWork",array.stream().filter(item->isWaitWork(item)).collect(Collectors.toList()).size() == 0 ? false : true);
        //检测有无施工中单据,定义：数据查询都是明细，所以判断都是，方案状态是confirm，完成日期有为空的
        reJson.put("haveWaitWork",array.stream().filter(item->isHaveWork(item)).collect(Collectors.toList()).size() == 0 ? false : true);
        //检测有无待质检单据,定义：数据查询都是明细，所以判断都是，方案状态是confirm，整单完成施工标记为true
        reJson.put("haveWaitTest",isHaveTest(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return "confirm".equals(itemJson.getString("STATE"))
                    && itemJson.get("CONFIRM_DATE") != null
                    && itemJson.getBoolean("FINISH_WORK")
                    && 2 != itemJson.getInteger("LOCK_STATE");
        }));
        //检测有无待收款单据,定义：数据查询都是明细，所以判断都是，方案状态是质检
        reJson.put("haveWaitMoney",array.stream().filter(item->isHaveWaiteMoney(item)).collect(Collectors.toList()).size() == 0 ? false : true);
        //检测有无待收款单据,定义：数据查询都是明细，所以判断都是，存在工单锁定状态
        reJson.put("haveLock",array.stream().filter(item->isHaveLock(item)).collect(Collectors.toList()).size() == 0 ? false : true);

        //检测是否存在，整单都是配件的
        reJson.put("allPart", array.size() == 0 ? false :isAllPart(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return ("confirm".equals(itemJson.getString("STATE"))
                    && itemJson.get("CONFIRM_DATE") != null
                    && 2 != itemJson.getInteger("LOCK_STATE")) || !Objects.equals("confirm",itemJson.getString("STATE"));
        }));

        //检测是否存在，完工未领料的(整单存在工时 + ！找到工时没完工 + 找到配件没完工)  FINISH_DATE_ITEM 明细行的完成时间
        reJson.put("FinishWorkNoReceive", isPlanHaveWork(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return ("confirm".equals(itemJson.getString("STATE"))
                    && itemJson.get("CONFIRM_DATE") != null
                    && 2 != itemJson.getInteger("LOCK_STATE"));
        })  && isPlanHaveWorkFinish(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return ("confirm".equals(itemJson.getString("STATE"))
                    && itemJson.get("CONFIRM_DATE") != null
                    && 2 != itemJson.getInteger("LOCK_STATE")
                    && itemJson.get("FINISH_DATE_ITEM") == null );
        }) && isPlanHaveNoworkUnFinish(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return "confirm".equals(itemJson.getString("STATE"))
                    && itemJson.get("CONFIRM_DATE") != null
                    && 2 == itemJson.getInteger("LOCK_STATE")
                    && itemJson.get("FINISH_DATE_ITEM") == null ;
        }) );

        //检测存在方案已领料
        reJson.put("haveServicePlanPick",haveServicePlanPick(array,(item)->{
            JSONObject itemJson = (JSONObject)item;
            return  itemJson.get("FITTING") != null
                    && ((JSONObject) item).getDouble("QTY_RECEIVE").equals(
                        Arith.sub(itemJson.getDouble("SALE_QTY"),itemJson.getDouble("QTY_END")) );
        },(item)->{
            JSONObject itemJson = (JSONObject)item;
            return  itemJson.get("FITTING") != null;
        }));

        //检测是否存在确认状态和质检状态的方案单
        reJson.put("haveConfirmToReci",array.stream().filter(item ->{
            JSONObject itemJson = (JSONObject)item;
            return "qualityTest".equals(itemJson.getString("STATE")) || "confirm".equals(itemJson.getString("STATE"));
        }).collect(Collectors.toList()).size() == 0 ? false : true);
        return reJson;
    }


    /**
     * 将服务方案分组，对该服务方案的数据进行条件过滤并判断是否达到数量
     * @param array
     * @param filterCondition  过滤条件
     * @param filterConditionCount  过滤后需要达到的数量
     * @return
     */
    private boolean haveServicePlanPick(JSONArray array,Predicate filterCondition,Predicate filterConditionCount) {
        array = Optional.ofNullable(array).orElseGet(()-> new JSONArray());

        //根据方案号分组
        Map groupMap = array.stream().collect(Collectors.groupingBy(item->{
            return ((JSONObject)item).getString("ID");
        }));
        //分组方案进行迭代，找到一个方案可以质检，直接返回
        Set setset = groupMap.keySet();
        if(setset.size() != 0){
            Iterator iterator = setset.iterator();
            while (iterator.hasNext()){
                List list = (ArrayList) groupMap.get(iterator.next());

                List filterList = (List) list.stream().filter(item ->{
                    JSONObject itemJson = (JSONObject)item;
                    return filterCondition.test(itemJson);
                }).collect(Collectors.toList());

                List filterCount = (List) list.stream().filter(item ->{
                    JSONObject itemJson = (JSONObject)item;
                    return filterConditionCount.test(itemJson);
                }).collect(Collectors.toList());
                if(list.size() != 0) return true;
            }
        }else{
            return false;
        }
        return false;
    }

    /**
     * 获取服务方案id
     * @param item
     * @return
     */
    public Object getServiceId(Object item){
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return json.get("ID");
    }

    /**
     * 是否有终止方案
     * @param item
     * @return
     */
    public boolean haveEndServicePlan(Object item){
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return "termination".equals(json.getString("STATE"));
    }

    /**
     * 是否待施工
     * @param item
     * @return
     */
    private boolean isWaitWork(Object item) {
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return "confirm".equals(json.getString("STATE"))
                && json.getInteger("WORK_COUNT") == 0;
    }

    /**
     * 存在精品方案--》找到就返回真，否则假
     * @param
     * @return
     */
    private boolean isAllPart(JSONArray array,Predicate vehi) {
        return !isPlanGroupCommon(array,vehi); //
    }


    /**
     * 存在一个方案是否存在工时
     * @param
     * @return
     */
    private boolean isPlanHaveWork(JSONArray array,Predicate vehi) {
        return isPlanGroupCommon(array,vehi); //
    }

    /**
     * 存在一个方案工时全部完成
     * @param
     * @return
     */
    private boolean isPlanHaveWorkFinish(JSONArray array,Predicate vehi) {
        return !isPlanGroupCommon(array,vehi); //
    }

    /**
     * 一个方案存在配件未完成
     * @param
     * @return
     */
    private boolean isPlanHaveNoworkUnFinish(JSONArray array,Predicate vehi) {
        return isPlanGroupCommon(array,vehi); //
    }


    /**
     * 是否存在施工中单据，存在：返回：true
     * @param item
     * @return
     */
    private boolean isHaveWork(Object item) {
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return "confirm".equals(json.getString("STATE"))
                && json.get("CONFIRM_DATE") != null
                && !json.getBoolean("FINISH_WORK")
                && json.get("FINISH_DATE_ITEM") == null
                && 0 == json.getInteger("LOCK_STATE")
                && json.getInteger("WORK_COUNT") != 0;
    }

    /**
     * 是否存在质检中单据，存在：返回：true
     * @param array
     * @return
     */
    private boolean isHaveTest(JSONArray array, Predicate vehi) {
        return isPlanGroupCommon(array,vehi);
    }

    private boolean isPlanGroupCommon(JSONArray array,Predicate vehi) {
        array = Optional.ofNullable(array).orElseGet(()-> new JSONArray());

        //根据方案号分组
        Map groupMap = array.stream().collect(Collectors.groupingBy(item->{
            return ((JSONObject)item).getString("ID");
        }));
        //分组方案进行迭代，找到一个方案可以质检，直接返回
        Set setset = groupMap.keySet();
        if(setset.size() != 0){
            Iterator iterator = setset.iterator();
            while (iterator.hasNext()){
                List list = (ArrayList) groupMap.get(iterator.next());

                list = (List) list.stream().filter(item ->{
                    JSONObject itemJson = (JSONObject)item;
                    return vehi.test(itemJson);
                }).collect(Collectors.toList());
                if(list.size() != 0) return true;
            }
        }else{
            return false;
        }
        return false;
    }



    /**
     * 待收款
     * @param item
     * @return
     */
    private boolean isHaveWaiteMoney(Object item) {
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return "qualityTest".equals(json.getString("STATE"));
    }


    /**
     * 是否存在锁定单据
     * @param item
     * @return
     */
    private boolean isHaveLock(Object item) {
        JSONObject json = Optional.ofNullable((JSONObject)item).orElseGet(()-> new JSONObject());
        return 1 == json.getInteger("LOCK_STATE");
    }

    /**
     * 是否存在已质检单据
     * @param json
     * @return
     */
    protected boolean isHaveReci(JSONObject json){
        JSONArray planArray = SpringManager.getBean(ServicePlanDao.class).vehiclePlanReci(json);
        if(planArray.size() != 0 && planArray.getJSONObject(0).getDoubleValue("AMOUNT")>0) return true;
        return false;
    }


    /**
     * 返回内协接车状态
     * @param json
     * @return
     */
    protected String obtainInnerPickCar(JSONObject json){
        JSONArray innerPickCarArray = SpringManager.getBean(ServicePlanDao.class).vehicleInnerPickUpCar(json);
        return innerPickCarArray == null || innerPickCarArray.size() == 0 ? null : innerPickCarArray.getJSONObject(0).getString("STATE");
    }
}